home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / mail / YAM22src.lha / YAM_US.c < prev    next >
C/C++ Source or Header  |  2000-11-03  |  19KB  |  486 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 2000  Marcel Beck <mbeck@yam.ch>
  5.  
  6.  This program is free software; you can redistribute it and/or modify
  7.  it under the terms of the GNU General Public License as published by
  8.  the Free Software Foundation; either version 2 of the License, or
  9.  (at your option) any later version.
  10.  
  11.  This program is distributed in the hope that it will be useful,
  12.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  GNU General Public License for more details.
  15.  
  16.  You should have received a copy of the GNU General Public License
  17.  along with this program; if not, write to the Free Software
  18.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20.  YAM Official Support Site :  http://www.yam.ch
  21.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  22.  
  23. ***************************************************************************/
  24.  
  25. #include "YAM.h"
  26.  
  27. /***************************************************************************
  28.  Module: User list
  29. ***************************************************************************/
  30.  
  31. /// US_GetCurrentUser
  32. //  Gets pointer current user from user database
  33. struct User *US_GetCurrentUser(void)
  34. {
  35.    int i;
  36.    struct User *u = NULL;
  37.    for (i = 0; i < G->Users.Num; i++) if (G->Users.User[i].ID == G->Users.CurrentID) u = &G->Users.User[i];
  38.    return u;
  39. }
  40. ///
  41. /// US_SaveUsers
  42. //  Saves user database to .users
  43. void US_SaveUsers(void)
  44. {
  45.    FILE *fh;
  46.    char *fname = "PROGDIR:.users";
  47.    int i;
  48.  
  49.    for (i = 0; i < G->Users.Num; i++) if (!G->Users.User[i].Limited) break;
  50.    if (i == G->Users.Num) G->Users.User[0].Limited = FALSE;
  51.    if (fh = fopen(fname, "w"))
  52.    {
  53.       int i;
  54.       fputs("YUS2 - YAM Users\n", fh);
  55.       for (i = 0; i < G->Users.Num; i++)
  56.       {
  57.          struct User *u = &G->Users.User[i];
  58.          if (u->Name) fprintf(fh, "@USER %s\n%s\n%ld\n%s\n@ENDUSER\n", u->Name, u->MailDir, u->Limited*4+u->UseAddr*2+u->UseDict, Encrypt(u->Password));
  59.       }
  60.       fclose(fh);
  61.       AppendLogVerbose(62, GetStr(MSG_LOG_SavingUsers), "", "", "", "");
  62.    }
  63.    else ER_NewError(GetStr(MSG_ER_CantCreateFile), fname, NULL);
  64. }
  65. ///
  66. /// US_LoadUsers
  67. //  Loads user database from .users
  68. void US_LoadUsers(void)
  69. {
  70.    BOOL save = FALSE;
  71.    FILE *fh;
  72.    char buffer[SIZE_LARGE];
  73.    clear(&G->Users, sizeof(struct Users));
  74.    G->Users.Num = 0;
  75.    if (fh = fopen("PROGDIR:.users", "r"))
  76.    {
  77.       BOOL hasmanager = FALSE;
  78.       GetLine(fh, buffer, SIZE_LARGE);
  79.       if (!strncmp(buffer,"YUS",3))
  80.       {
  81.          int ver = buffer[3]-'0';
  82.          while (GetLine(fh, buffer, SIZE_LARGE))
  83.          {
  84.             if (!strncmp(buffer, "@USER", 5))
  85.             {
  86.                struct User *u = &G->Users.User[G->Users.Num];
  87.                stccpy(u->Name, Trim(&buffer[6]), SIZE_NAME);
  88.                stccpy(u->MailDir, Trim(GetLine(fh, buffer, SIZE_LARGE)), SIZE_PATH);
  89.                if (!*u->MailDir) { stccpy(u->MailDir, G->MA_MailDir, SIZE_PATH); save = TRUE; }
  90.                if (FileType(u->MailDir) != 2)
  91.                {
  92.                   ER_NewError(GetStr(MSG_ER_UserRemoved), u->MailDir, u->Name);
  93.                   u->Name[0] = 0;
  94.                   save = TRUE;
  95.                }
  96.                else
  97.                {
  98.                   int flags = atoi(Trim(GetLine(fh, buffer, SIZE_LARGE)));
  99.                   u->Limited = (flags&4) == 4;
  100.                   u->UseAddr = (flags&2) == 2;
  101.                   u->UseDict = (flags&1) == 1;
  102.                   if (!u->Limited) hasmanager = TRUE;
  103.                   if (ver >= 2) stccpy(u->Password, Decrypt(GetLine(fh, buffer, SIZE_LARGE)), SIZE_PASSWORD);
  104.                   u->ID = GetSimpleID();
  105.                   G->Users.Num++;
  106.                }
  107.                while (GetLine(fh, buffer, SIZE_LARGE)) if (!strcmp(buffer, "@ENDUSER")) break;
  108.             }
  109.          }
  110.       }
  111.       fclose(fh);
  112.       if (!hasmanager) { G->Users.User[0].Limited = FALSE; save = TRUE; }
  113.    }
  114.    if (!G->Users.Num)
  115.    {
  116.       struct User *u = &G->Users.User[0];
  117.       stccpy(u->MailDir, G->MA_MailDir, SIZE_PATH);
  118.       u->UseAddr = u->UseDict = TRUE;
  119.       u->ID = GetSimpleID();
  120.       G->Users.Num = 1;
  121.       save = TRUE;
  122.    }
  123.    if (save) US_SaveUsers();
  124. }
  125. ///
  126. /// US_PromptForPassword
  127. //  User login: asks for user password
  128. BOOL US_PromptForPassword(struct User *u, APTR win)
  129. {
  130.    char passwd[SIZE_PASSWORD];
  131.  
  132.    do {
  133.       *passwd = 0;
  134.       if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_US_WaitLogin), GetStr(MSG_US_EnterPassword), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, win)) return FALSE;
  135.    } while (strcmp(passwd, u->Password));
  136.    return TRUE;
  137. }
  138. ///
  139. /// US_Login
  140. //  User login: puts up user list and waits for a selection
  141. BOOL US_Login(char *username, char *password, char *maildir, char *prefsfile)
  142. {
  143.    int i, user = -1;
  144.    APTR button, button0, group;
  145.    struct User *u;
  146.    BOOL loggedin = TRUE;
  147.  
  148.    US_LoadUsers();
  149.    if (username)
  150.    {
  151.       for (i = 0; i < G->Users.Num; i++) if (!stricmp(G->Users.User[i].Name, username)) user = i;
  152.    }
  153.    if (user < 0)
  154.    {
  155.       password = NULL;
  156.       if (G->Users.Num > 1)
  157.          if (DoMethod(G->AY_List, MUIM_Group_InitChange))
  158.          {
  159.             group = ColGroup(2), End;
  160.             for (i = 0; i < G->Users.Num; i++)
  161.             {
  162.                button = MakeButton(G->Users.User[i].Name);
  163.                if (!i) button0 = button;
  164.                DoMethod(group, OM_ADDMEMBER, button);
  165.                DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_Application_ReturnID, ID_LOGIN+i);
  166.             }
  167.             if (i%2 == 1) DoMethod(group, OM_ADDMEMBER, HSpace(0));
  168.             DoMethod(G->AY_List, OM_ADDMEMBER, group);
  169.             DoMethod(G->AY_List, MUIM_Group_ExitChange);
  170.             set(G->AY_Text, MUIA_ShowMe, TRUE);
  171.             set(G->AY_Text, MUIA_Gauge_InfoText, GetStr(MSG_US_WaitLogin));
  172.             set(G->AY_Group, MUIA_Group_ActivePage, 1);
  173.             set(G->AY_Win, MUIA_Window_ActiveObject, button0);
  174.             set(G->AY_Win, MUIA_Window_Open, TRUE);
  175.             while (user == -1)
  176.             {
  177.                ULONG signals;
  178.                long winopen, iconified;
  179.                get(G->AY_Win, MUIA_Window_Open, &winopen);
  180.                get(G->App, MUIA_Application_Iconified, &iconified);
  181.                if (!winopen && !iconified) return FALSE;
  182.                if ((i = DoMethod(G->App, MUIM_Application_Input, &signals)-ID_LOGIN) >= 0 && i < G->Users.Num) user = i;
  183.                else if (signals) Wait(signals);
  184.             }
  185.             set(G->AY_Group, MUIA_Group_ActivePage, 0);
  186.             DoMethod(G->AY_List, MUIM_Group_InitChange);
  187.             DoMethod(G->AY_List, OM_REMMEMBER, group);
  188.             DoMethod(G->AY_List, MUIM_Group_ExitChange);
  189.          }
  190.          else user = 0;
  191.       else user = 0;
  192.    }
  193.    u = &G->Users.User[user];
  194.    G->Users.CurrentID = u->ID;
  195.    strcpy(G->MA_MailDir, maildir ? maildir : u->MailDir);
  196.    if (prefsfile) strcpy(G->CO_PrefsFile, prefsfile); else strmfp(G->CO_PrefsFile, G->MA_MailDir, ".config");
  197.    strmfp(G->AB_Filename, u->UseAddr ? G->ProgDir : G->MA_MailDir, ".addressbook");
  198.    strmfp(G->DI_Filename, u->UseDict ? G->ProgDir : G->MA_MailDir, ".glossary");
  199.    if (u->Password[0])
  200.       if (password) loggedin = (!strcmp(password, u->Password) || *password == '\01');
  201.       else loggedin = US_PromptForPassword(u, G->AY_Win);
  202.    return loggedin;
  203. }
  204. ///
  205. /// US_DelFunc
  206. //  Removes a user from the user database
  207. SAVEDS void US_DelFunc(void)
  208. {
  209.    int i, m;
  210.    struct User *user;
  211.    APTR lv = G->US->GUI.LV_USERS;
  212.    get(lv, MUIA_NList_Active, &i);
  213.    DoMethod(lv, MUIM_NList_GetEntry, i, &user);
  214.    if (*user->MailDir)
  215.    {
  216.       if (!(m = MUI_Request(G->App, G->US->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_US_RemoveReqGads), GetStr(MSG_US_RemoveReq)))) return;
  217.       if (m == 1) DeleteMailDir(user->MailDir, TRUE);
  218.    }
  219.    DoMethod(lv, MUIM_NList_Remove, i);
  220. }
  221. MakeHook(US_DelHook, US_DelFunc);
  222. ///
  223. /// US_AddFunc
  224. //  Adds a new user to the user database
  225. SAVEDS void US_AddFunc(void)
  226. {
  227.    struct US_GUIData *gui = &G->US->GUI;
  228.    struct User user;
  229.    int n;
  230.    get(gui->LV_USERS, MUIA_NList_Entries, &n);
  231.    if (n < MAXUSERS-1)
  232.    {
  233.       clear(&user, sizeof(struct User));
  234.       user.Limited = user.IsNew = TRUE;
  235.       DoMethod(gui->LV_USERS, MUIM_NList_InsertSingle, &user, MUIV_NList_Insert_Bottom);
  236.       set(gui->LV_USERS, MUIA_NList_Active, MUIV_NList_Active_Bottom);
  237.       set(gui->WI, MUIA_Window_ActiveObject, gui->ST_USER);
  238.    }
  239. }
  240. MakeHook(US_AddHook, US_AddFunc);
  241. ///
  242. /// US_SaveUserList
  243. //  Initializes configuration files for new users and saves the user database
  244. BOOL US_SaveUserList(void)
  245. {
  246.    int i;
  247.  
  248.    get(G->US->GUI.LV_USERS, MUIA_NList_Entries, &G->Users.Num);
  249.    for (i = 0; i < G->Users.Num; i++)
  250.    {
  251.       struct User *u;
  252.       BOOL valid = FALSE;
  253.       DoMethod(G->US->GUI.LV_USERS, MUIM_NList_GetEntry, i, &u);
  254.       G->Users.User[i] = *u;
  255.       if (*u->Name)
  256.          if (*u->MailDir)
  257.             if (FileType(u->MailDir) != 2)
  258.             {
  259.                if (MUI_Request(G->App, G->US->GUI.WI, 0, GetStr(MSG_MA_MUsers), GetStr(MSG_YesNoReq), GetStr(MSG_US_ErrorNoDirectory)))
  260.                   if (CreateDirectory(u->MailDir)) valid = TRUE;
  261.                   else ER_NewError(GetStr(MSG_ER_CantCreateDir), u->MailDir, NULL);
  262.             }
  263.             else valid = TRUE;
  264.          else ER_NewError(GetStr(MSG_ER_MissingDirectory), NULL, NULL);
  265.       else ER_NewError(GetStr(MSG_ER_MissingName), NULL, NULL);
  266.       if (!valid)
  267.       {
  268.          set(G->US->GUI.LV_USERS, MUIA_NList_Active, i);
  269.          return FALSE;
  270.       }
  271.       if (u->Clone && u->IsNew)
  272.       {
  273.          char dest[SIZE_PATHFILE];
  274.          strmfp(dest, u->MailDir, ".addressbook"); CopyFile(dest, NULL, G->AB_Filename, NULL);
  275.          strmfp(dest, u->MailDir, ".glossary");    CopyFile(dest, NULL, G->DI_Filename, NULL);
  276.          strmfp(dest, u->MailDir, ".config");      CopyFile(dest, NULL, G->CO_PrefsFile, NULL);
  277.       }
  278.    }
  279.    US_SaveUsers();
  280.    return TRUE;
  281. }
  282. ///
  283. /// US_OpenFunc
  284. //  Opens and initializes user list window
  285. SAVEDS void US_OpenFunc(void)
  286. {
  287.    if (!G->US)
  288.    {
  289.       int i;
  290.       struct User *u;
  291.       for (i = 0; i < G->Users.Num; i++) if (G->Users.User[i].ID == G->Users.CurrentID) u = &G->Users.User[i];
  292.       if (!*G->Users.User[0].Name) stccpy(G->Users.User[0].Name, C->RealName, SIZE_NAME);
  293.       if (!(G->US = US_New(!u->Limited))) return;
  294.       if (!SafeOpenWindow(G->US->GUI.WI)) { DisposeModulePush(&G->US); return; }
  295.       for (i = 0; i < G->Users.Num; i++) DoMethod(G->US->GUI.LV_USERS, MUIM_NList_InsertSingle, &G->Users.User[i], MUIV_NList_Insert_Bottom);
  296.       set(G->US->GUI.LV_USERS, MUIA_NList_Active, 0);
  297.    }
  298. }
  299. MakeHook(US_OpenHook, US_OpenFunc);
  300. ///
  301. /// US_CloseFunc
  302. //  Closes user list window
  303. SAVEDS void US_CloseFunc(void)
  304. {
  305.    if (US_SaveUserList()) DisposeModulePush(&G->US);
  306. }
  307. MakeHook(US_CloseHook, US_CloseFunc);
  308. ///
  309. /// US_GetUSEntryFunc
  310. //  Fills form with data from selected list entry
  311. SAVEDS void US_GetUSEntryFunc(void)
  312. {
  313.    struct User *user;
  314.    struct US_GUIData *gui = &G->US->GUI;
  315.    BOOL notallowed, iscurrent = FALSE, limited = !G->US->Supervisor;
  316.    int act;
  317.    char *md = "-";
  318.  
  319.    get(gui->LV_USERS, MUIA_NList_Active, &act);
  320.    if (act != MUIV_NList_Active_Off)
  321.    {
  322.       DoMethod(gui->LV_USERS, MUIM_NList_GetEntry, act, &user);
  323.       iscurrent = user->ID == G->Users.CurrentID;
  324.       nnset(gui->ST_USER,    MUIA_String_Contents, user->Name);
  325.       nnset(gui->ST_MAILDIR, MUIA_String_Contents, md = user->MailDir);
  326.       nnset(gui->ST_PASSWD,  MUIA_String_Contents, user->Password);
  327.       nnset(gui->CH_USEADDR, MUIA_Selected, user->UseAddr);
  328.       nnset(gui->CH_USEDICT, MUIA_Selected, user->UseDict);
  329.       nnset(gui->CH_ROOT,    MUIA_Selected, !user->Limited);
  330.       nnset(gui->CH_CLONE,   MUIA_Selected, user->Clone);
  331.       notallowed = limited && !iscurrent;
  332.       set(gui->ST_USER,    MUIA_Disabled, notallowed);
  333.       set(gui->CH_USEDICT, MUIA_Disabled, notallowed || !act);
  334.       set(gui->CH_USEADDR, MUIA_Disabled, notallowed || !act);
  335.       set(gui->CH_CLONE,   MUIA_Disabled, !user->IsNew || !act);
  336.       set(gui->PO_MAILDIR, MUIA_Disabled, limited || !act);
  337.       set(gui->CH_ROOT,    MUIA_Disabled, limited);
  338.       set(gui->ST_PASSWD,  MUIA_Disabled, notallowed);
  339.       set(gui->BT_DEL,     MUIA_Disabled, !act || iscurrent);
  340.    }
  341.    else DoMethod(G->App, MUIM_MultiSet, MUIA_Disabled, TRUE, gui->ST_USER, gui->ST_PASSWD, gui->PO_MAILDIR, gui->CH_USEDICT, gui->CH_USEADDR, gui->CH_ROOT, gui->CH_CLONE, gui->BT_DEL, NULL);
  342. }
  343. MakeHook(US_GetUSEntryHook,US_GetUSEntryFunc);
  344. ///
  345. /// US_PutUSEntryFunc
  346. //  Fills form data into selected list entry
  347. SAVEDS void US_PutUSEntryFunc(void)
  348. {
  349.    struct User *user = NULL;
  350.    struct US_GUIData *gui = &G->US->GUI;
  351.  
  352.    DoMethod(gui->LV_USERS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &user);
  353.    if (user)
  354.    {
  355.       GetMUIString(user->Name, gui->ST_USER);
  356.       GetMUIString(user->MailDir, gui->ST_MAILDIR);
  357.       GetMUIString(user->Password, gui->ST_PASSWD);
  358.       user->UseAddr = GetMUICheck(gui->CH_USEADDR);
  359.       user->UseDict = GetMUICheck(gui->CH_USEDICT);
  360.       user->Limited = !GetMUICheck(gui->CH_ROOT);
  361.       user->Clone   = GetMUICheck(gui->CH_CLONE);
  362.       DoMethod(gui->LV_USERS, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  363.    }
  364. }
  365. MakeHook(US_PutUSEntryHook,US_PutUSEntryFunc);
  366. ///
  367.  
  368. /*** GUI ***/
  369. /// US_LV_ConFunc
  370. //  User listview construction hook
  371. SAVEDS ASM struct User *US_LV_ConFunc(REG(a1) struct User *user)
  372. {
  373.    struct User *entry = malloc(sizeof(struct User));
  374.    *entry = *user;
  375.    return entry;
  376. }
  377. MakeHook(US_LV_ConHook, US_LV_ConFunc);
  378. ///
  379. /// US_LV_DspFunc
  380. //  User listview display hook
  381. SAVEDS ASM long US_LV_DspFunc(REG(a2) char **array, REG(a1) struct User *entry)
  382. {
  383.    if (entry)
  384.    {
  385.       array[0] = entry->Name;
  386.       array[1] = entry->MailDir;
  387.       if (entry->ID == G->Users.CurrentID) array[DISPLAY_ARRAY_MAX] = "\0338";
  388.    }
  389.    else
  390.    {
  391.       array[0] = GetStr(MSG_US_TitleUserName);
  392.       array[1] = GetStr(MSG_US_TitleMailDir);
  393.    }
  394.    return 0;
  395. }
  396. MakeHook(US_LV_DspHook,US_LV_DspFunc);
  397. ///
  398. /// US_New
  399. //  Creates user list window
  400. struct US_ClassData *US_New(BOOL supervisor)
  401. {
  402.    struct US_ClassData *data;
  403.  
  404.    if (data = calloc(1, sizeof(struct US_ClassData)))
  405.    {
  406.       data->Supervisor = supervisor;
  407.       data->GUI.WI = WindowObject,
  408.          MUIA_Window_Title, GetStr(MSG_MA_MUsers),
  409.          MUIA_HelpNode, "US_W",
  410.          MUIA_Window_ID, MAKE_ID('U','S','E','R'),
  411.          WindowContents, VGroup,
  412.             Child, data->GUI.LV_USERS = NListviewObject,
  413.                MUIA_CycleChain, 1,
  414.                MUIA_NListview_NList, NListObject,
  415.                   InputListFrame,
  416.                   MUIA_NList_ConstructHook, &US_LV_ConHook,
  417.                   MUIA_NList_DestructHook, &GeneralDesHook,
  418.                   MUIA_NList_DisplayHook, &US_LV_DspHook,
  419.                   MUIA_NList_DisplayHook, &MA_LV_FDspFuncHook,
  420.                   MUIA_NList_TitleSeparator, TRUE,
  421.                   MUIA_NList_Title, TRUE,
  422.                   MUIA_NList_Format, "BAR,",
  423.                End,
  424.             End,
  425.             Child, VGroup, GroupFrameT(GetStr(MSG_MA_Settings)),
  426.                Child, ColGroup(2),
  427.                   Child, Label2(GetStr(MSG_US_UserName)),
  428.                   Child, data->GUI.ST_USER = MakeString(SIZE_NAME, GetStr(MSG_US_UserName)),
  429.                   Child, Label2(GetStr(MSG_US_Password)),
  430.                   Child, data->GUI.ST_PASSWD = MakePassString(GetStr(MSG_US_Password)),
  431.                   Child, Label2(GetStr(MSG_US_MailDirectory)),
  432.                   Child, data->GUI.PO_MAILDIR = PopaslObject,
  433.                      MUIA_Popasl_Type,ASL_FileRequest,
  434.                      MUIA_Popstring_String,data->GUI.ST_MAILDIR = MakeString(SIZE_PATH,GetStr(MSG_US_MailDirectory)),
  435.                      MUIA_Popstring_Button,PopButton(MUII_PopDrawer),
  436.                      ASLFR_DrawersOnly, TRUE,
  437.                   End,
  438.                End,
  439.                Child, VGroup,
  440.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_USEADDR, GetStr(MSG_US_GlobalAddrBook)),
  441.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_USEDICT, GetStr(MSG_US_GlobalDict)),
  442.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_ROOT,GetStr(MSG_US_SuperVisor)),
  443.                End,
  444.                Child, VGroup,
  445.                   MUIA_ShowMe, supervisor,
  446.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_CLONE, GetStr(MSG_US_CopyConfig)),
  447.                End,
  448.             End,
  449.             Child, ColGroup(3),
  450.                MUIA_ShowMe, supervisor,
  451.                Child, data->GUI.BT_ADD = MakeButton(GetStr(MSG_US_AddUser)),
  452.                Child, data->GUI.BT_DEL = MakeButton(GetStr(MSG_US_DelUser)),
  453.             End,
  454.          End,
  455.       End;
  456.       if (data->GUI.WI)
  457.       {
  458.          SetHelp(data->GUI.ST_USER   ,MSG_HELP_US_ST_USER);
  459.          SetHelp(data->GUI.ST_MAILDIR,MSG_HELP_US_ST_MAILDIR);
  460.          SetHelp(data->GUI.ST_PASSWD ,MSG_HELP_US_ST_PASSWD);
  461.          SetHelp(data->GUI.CH_USEADDR,MSG_HELP_US_CH_USEADDR);
  462.          SetHelp(data->GUI.CH_USEDICT,MSG_HELP_US_CH_USEDICT);
  463.          SetHelp(data->GUI.CH_CLONE  ,MSG_HELP_US_CH_CLONE);
  464.          SetHelp(data->GUI.CH_ROOT   ,MSG_HELP_US_CH_ROOT);
  465.          SetHelp(data->GUI.BT_ADD    ,MSG_HELP_US_BT_ADD);
  466.          SetHelp(data->GUI.BT_DEL    ,MSG_HELP_US_BT_DEL);
  467.          DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
  468.          DoMethod(data->GUI.LV_USERS,  MUIM_Notify,MUIA_List_Active,        MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_GetUSEntryHook);
  469.          DoMethod(data->GUI.ST_USER,   MUIM_Notify,MUIA_String_Contents,    MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  470.          DoMethod(data->GUI.ST_MAILDIR,MUIM_Notify,MUIA_String_Contents,    MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  471.          DoMethod(data->GUI.ST_PASSWD, MUIM_Notify,MUIA_String_Contents,    MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  472.          DoMethod(data->GUI.CH_USEADDR,MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  473.          DoMethod(data->GUI.CH_USEDICT,MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  474.          DoMethod(data->GUI.CH_ROOT,   MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  475.          DoMethod(data->GUI.CH_CLONE,  MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  476.          DoMethod(data->GUI.BT_ADD,    MUIM_Notify,MUIA_Pressed,            FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&US_AddHook);
  477.          DoMethod(data->GUI.BT_DEL,    MUIM_Notify,MUIA_Pressed,            FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&US_DelHook);
  478.          DoMethod(data->GUI.WI,        MUIM_Notify,MUIA_Window_CloseRequest,TRUE          ,MUIV_Notify_Application,2,MUIM_CallHook,&US_CloseHook);
  479.          return data;
  480.       }
  481.       free(data);
  482.    }
  483.    return NULL;
  484. }
  485. ///
  486.